#ifndef __ECHOSERVER_H__
#define __ECHOSERVER_H__

#include "Threadpool.h"
#include "TcpConnection.h"
#include "TcpServer.h"
#include "KeyRecommander.h"
#include "Mylogger.h"
#include "MyRedis.h"
#include "ConfigFile.h"
#include "Dictionary.h"
#include "webPageSearcher.h"
#include<nlohmann/json.hpp>


#include <iostream>
#include <unistd.h>

using json = nlohmann::json;
using std::cout;
using std::endl;


class MyTask
{
public:
    MyTask(const string &msg, const TcpConnectionPtr &con,int flag,KeyRecommander &key,WebPageSearcher &web)
    : _msg(msg)
    , _con(con)
    ,_flag(flag)
    ,_key(key)
    ,_web(web)
    {

    }
    void process()
    {
        switch(_flag)
        {
            case 1:
            {
                //关键字查询
                //cout<<"-----------------Key_value find"<<endl;
                //KeyRecommander keys(_msg,this->_con,conf["dictEnPath"],conf["dictZhPath"],conf["indexEnPath"],conf["indexZhPath"]);
                
                string msg = _key.execute(_msg);
                _con.get()->sendInLoop(msg);
                
                break;
            }
            case 2:
            {
                //网页查询
                //cout<<"-----------------page find"<<endl;
                string msg = _web.doQuery(_msg);
                _con.get()->sendInLoop(msg);
                break;
            }
            case 3:
            {
                _con.get()->send(_msg);
                break;
            }
        }
    }
private:
    string _msg;
    TcpConnectionPtr _con;
    int _flag;
    KeyRecommander & _key;
    WebPageSearcher &_web;
};

class EchoServer
{
public:
    EchoServer(size_t threadNum, size_t queSize
               , const string &ip, unsigned short port,const string &dictEn,
               const string &dictZh, const string &indexEn, const string &indexZh)
    : _pool(threadNum, queSize)
    , _server(ip, port)
    ,_keys(dictEn,dictZh,indexEn,indexZh)
    {
        
    }

    ~EchoServer()
    {

    }

    void start()
    {
        _pool.start();
        using namespace std::placeholders;//占位符
        _server.setAllCallback(std::bind(&EchoServer::onConnection, this, _1)
                               , std::bind(&EchoServer::onMessage, this, _1)
                               , std::bind(&EchoServer::onClose, this, _1));
        _server.start();
    }

    void stop()
    {
        _pool.stop();
        _server.stop();
    }
    
    //TCP网编编程中的三个事件（从类外传递进来）
    void onConnection(const TcpConnectionPtr &con)
    {
        string msg = con->toString();
        msg+=" has connected!";
        LogInfo("%d{%Y-%m-%d %H:%M:%S} %c [%p] %m%n",msg.c_str());
    }
    
    void onMessage(const TcpConnectionPtr &con)
    {
        
        
        int nu = con->recvInt();
        int len = con->recvInt();
        string msg = con->readmsg(len);

        string info = "client send msg  <--:"+msg;

        LogInfo("%d{%Y-%m-%d %H:%M:%S} %c [%p] %c %x: %m%n",info.c_str());
        switch(nu)
        {
        case 1:
            {
                string keyInfo = "关键字查询 ["+msg+"]";
                LogInfo("%d{%Y-%m-%d %H:%M:%S} %c [%p] %c %x: %m%n",keyInfo.c_str());
                
                    //去redis中找，找到了直接发送，没找到，再去文件中找
                    //string value = 
                MyRedis *ptr = MyRedis::getInstance();
                ptr->select(0);
                string value = ptr->get(msg);
                if(value.size()>1)
                {
                    MyTask task(value, con,3,_keys,_web);
                    _pool.addTask(std::bind(&MyTask::process, task));
                    LogInfo("%d{%Y-%m-%d %H:%M:%S} %c [%p] %c %x: %m%n","数据来源--redis");
                    break;
                }

                MyTask task(msg,con,1,_keys,_web);
                _pool.addTask(std::bind(&MyTask::process, task));
                break;
            }
        case 2:
            {
                string pageInfo = "网页查询 ["+msg+"]";
                LogInfo("%d{%Y-%m-%d %H:%M:%S} %c [%p] %c %x: %m%n",pageInfo.c_str());
                
                MyRedis *ptr = MyRedis::getInstance();
                ptr->select(1);
                string value = ptr->get(msg);
                if(value.size()>1)
                {
                    MyTask task(value, con,3,_keys,_web);
                    _pool.addTask(std::bind(&MyTask::process, task));
                    LogInfo("%d{%Y-%m-%d %H:%M:%S} %c [%p] %c %x: %m%n","数据来源--redis");
                    break;
                }
                MyTask task(msg,con,2,_keys,_web);
                _pool.addTask(std::bind(&MyTask::process, task));
                break;
            }
        }

    }
    
    void onClose(const TcpConnectionPtr &con)
    {
        cout << con->toString() << " has closed!" << endl;
        string info = con->toString()+"has closed";
        LogInfo("%d{%Y-%m-%d %H:%M:%S} %c [%p] %m%n",info.c_str());
    }

private:
    Threadpool _pool;
    TcpServer _server;
    KeyRecommander _keys;
    WebPageSearcher _web;
};

#endif
